package cn.bigcontainer.alt.meta.dto;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cn.bigcontainer.alt.meta.extension.MDeletor;
import cn.bigcontainer.alt.meta.extension.MImportor;
import cn.bigcontainer.alt.meta.extension.MListLoader;
import com.fasterxml.jackson.annotation.JsonIgnore;

import cn.bigcontainer.alt.common.util.WoJsonKit;
import cn.bigcontainer.alt.common.util.WoKit;
import cn.bigcontainer.alt.meta.exception.MException;
import cn.bigcontainer.alt.meta.extension.MListDataFilter;
import cn.bigcontainer.alt.meta.mapper.MAppMapper;
import cn.bigcontainer.alt.meta.mapper.MObjectMapper;
import cn.bigcontainer.alt.meta.mapper.MViewMapper;
import cn.bigcontainer.alt.meta.po.MApp;
import cn.bigcontainer.alt.meta.po.MObject;
import cn.bigcontainer.alt.meta.po.MView;
import cn.bigcontainer.alt.meta.po.MViewProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;

@Slf4j
public class MAppDto extends MApp {

    /**
     * 默认是菜单编号，前端提交过来的数据，仅放在内存中，不序列化到数据库
     */
    private String domprefix;

    public String getDomprefix() {
        return domprefix;
    }

    public void setDomprefix(String domprefix) {
        this.domprefix = domprefix;
    }

    /**
     * 应用容器tab/modal
     */
    private String container;

    public String getContainer() {
        return container;
    }

    public void setContainer(String container) {
        this.container = container;
    }

    public List<MViewDto> getViews() {
        return views;
    }

    public MViewDto getView (String viewId) {
        return views.stream().filter(v -> v.getId().equals(viewId)).findFirst().get();
    }

    public MViewDto getViewByType (String viewType) {
        return views.stream().filter(v -> v.getType().equals(viewType)).findFirst().get();
    }
    
    public void setViews(List<MViewDto> views) {
        this.views = views;
    }

    public MObjectDto getObject() {
        return object;
    }

    public void setObject(MObjectDto object) {
        this.object = object;
    }

    /**
     * 增删改查
     */
    public static final String TYPE_CRUD = "crud";

    /**
     * 增删改查
     */
    public static final String TYPE_FORM = "form";

    /**
     * 分组
     */
    public static final String TYPE_GRP = "group";

    /**
     * 工作流
     */
    public static final String TYPE_WORKFLOW = "workflow";

    /**
     * 列表编辑器
     */
    public static final String TYPE_LEDITOR = "leditor";

    /**
     * 左树右表导航
     */
    public static final String TYPE_NAV = "navigator";

    /**
     * 日历
     */
    public static final String TYPE_CALENDAR = "calendar";
    
    public static final String PREFIX_VIEW = "appView.";

    public static final String PREFIX_EXTENSION = "extension.";

    public static final String PARAM_LIST_TMPL = "listtemplate";

    public static final String PARAM_REQUEST_JSON = "requestjson";

    public static final String PARAM_APPS = "apps";
    
    /**
     * 关联的所有视图数据
     */
    @JsonIgnore
    private List<MViewDto> views = new ArrayList<>();

    @JsonIgnore
    private List<MAppDto> apps = new ArrayList<>();
    
    private MObjectDto object;

    public MAppDto() {
    }

    public MAppDto(MApp app) {
        super(app);
        for (String key : this.getData().keySet()) {
            if (key.startsWith(PREFIX_VIEW)) {
            	String viewId = app.getData().getString(key);
            	if (WoKit.isEmpty(viewId)) {
            		throw new MException(MException.APP_VIEW, app.getId(), key);
            	}
            	MView view = WoKit.getBean(MViewMapper.class).selectById(viewId);
                if (view == null) {
                	throw new MException(MException.VIEW, viewId);
                }
                views.add(new MViewDto(view, this));
            }
        }
        Collections.sort(views);
        MObject obj = WoKit.getBean(MObjectMapper.class).selectById(app.getObjectId());
        this.object = new MObjectDto(obj);
        List<String> ids = app.getData().getStringList(PARAM_APPS);
        if (ids.size() > 0) {
        	apps = WoKit.getDtos(MAppDto.class, WoKit.getBean(MAppMapper.class).selectBatchIds(ids));
        }
    }

    @JsonIgnore
    public MListDataFilter getListDataFilter () {
    	if (object == null) {
    		return null;
    	}
        return MObjectDto.getListFilter(this.id, data, getObject().getRequest());
    }

    @JsonIgnore
    public String getListTemplate () {
    	if (this.getObject().getRequest() != null) {
    		String tmpl = this.getObject().getRequest().getString(PARAM_LIST_TMPL);
    		if (tmpl != null) {
    			return tmpl;
    		}
    	}
        return data.getString(PARAM_LIST_TMPL, "meta/list");
    }

    public void setListTemplate (String listTemplate) {
        data.put(PARAM_LIST_TMPL, listTemplate);
    }

    /**
     * 根据id获取视图属性
     * @param id
     * @return
     */
    public MViewProperty getViewProperty (String id) {
        for (MViewDto v : views) {
            for (MViewProperty p : v.getProperties()) {
                if (p.getId().equals(id)) {
                    return p;
                }
            }
        }
        return null;
    }

    @JsonIgnore
    public Boolean getMetaShow () {
        return data.getBoolean(MObjectDto.PARAM_META_SHOW, false);
    }

    public void setMetaShow (Boolean metaShow) {
        data.put(MObjectDto.PARAM_META_SHOW, metaShow);
    }

    @JsonIgnore
    public Boolean getMetaShowViews () {
        for (MViewDto v : getViews()) {
            if (v.getMetaActive()) {
                return true;
            }
        }
        return false;
    }

    @JsonIgnore
    public String getRequestJson () {
        return WoJsonKit.writeAsString(getObject().getRequest());
    }

    @JsonIgnore
    public List<MAppDto> getApps() {
		return apps;
	}
    
    public MAppDto getApp(String app) {
    	return apps.stream().filter(e -> e.getId().equals(app)).findFirst().get();
    }
    
    /**
     * @param key
     * @return
     */
    public String getExtension (String key) {
		String ex = data.getString(key);
		if (WoKit.isEmpty(ex)) {
			ex = getObject().getRequest().getString(key);
		}
        if (WoKit.isEmpty(ex)) {
            ex = this.getId() + "." + key;
            if (!WoKit.containsBean(ex)) {
                return null;
            }
        }
		return ex;
	}

    private MDeletor deletor = null;

    public final static String PARAM_EXT_DELETE = PREFIX_EXTENSION + ".delete";

    /**
     *
     * @return
     */
    private MDeletor getExtensionDeletor () {
        if (deletor != null) {
            return deletor;
        }
        String ex = getExtension(PARAM_EXT_DELETE);
        if (WoKit.isEmpty(ex) || !WoKit.containsBean(ex)) {
            return null;
        }
        return deletor = WoKit.getBean(MDeletor.class, ex);
    }

    /**
     *
     * @param app
     * @param keyValues
     * @return
     */
    public MAppDto delete (MAppDto app, String keyValues) {
        MDeletor ex = getExtensionDeletor();
        if (ex != null) {
            return ex.delete(app, keyValues);
        }
        return null;
    }

    private MImportor importor = null;

    public final static String PARAM_EXT_IMPORT = PREFIX_EXTENSION + ".import";

    /**
     *
     * @return
     */
    private MImportor getExtensionImportor () {
        if (importor != null) {
            return importor;
        }
        String ex = getExtension(PARAM_EXT_IMPORT);
        if (WoKit.isEmpty(ex) || !WoKit.containsBean(ex)) {
            return null;
        }
        return importor = WoKit.getBean(MImportor.class, ex);
    }

    /**
     *
     * @param app
     * @param workbook
     * @return
     */
    public MAppDto importExcel (MAppDto app, Workbook workbook) {
        MImportor ex = getExtensionImportor();
        if (ex != null) {
            return ex.importExcel(app, workbook);
        }
        return null;
    }

}
